home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / macgambit-20-compiler-src-p1 / Runtime (.c & .h) / os_mac_Help.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-26  |  18.0 KB  |  773 lines  |  [TEXT/KAHL]

  1. #include <Windows.h>
  2.  
  3. /*----------------------------------------------------------------------*/
  4.  
  5. #define HELP_WIND_W     450
  6. #define HELP_MENU_H     20
  7. #define HELP_LINE_H     13
  8. #define HELP_LINES      21
  9. #define HELP_TOP_SPACE  5
  10. #define HELP_BOT_SPACE  1
  11. #define HELP_DESCENT    4
  12. #define HELP_LEFT_SPACE 5
  13.  
  14. #define HELP_INDEX_START 2
  15.  
  16. #define HELP_SCROLL_MAX (2*(HELP_LINES*HELP_LINE_H+HELP_TOP_SPACE+HELP_BOT_SPACE-15-15-16))
  17.  
  18. #define HELP_MENUS_MAX 20
  19. #define HELP_ITEMS_MAX 400
  20. #define HELP_MENUS_ID 200
  21.  
  22. #define HELP_CACHE_LENGTH 3000
  23. #define HELP_CACHE_BEFORE 1500
  24. #define HELP_NEWLINE 13
  25.  
  26. int help_error = 1;       /* error flag          */
  27. static int help_refnum;   /* refnum of help file */
  28. static long help_length;  /* length of help file */
  29. static long help_prefix;  /* length of prefix    */
  30.  
  31. static char help_buffer[HELP_CACHE_LENGTH+2]; /* has newline at both ends */
  32. static char *help_cache, *help_cache_end;     /* limits of cache block    */
  33. static char *help_line,  *help_line_end;      /* limits of current line   */
  34. static long help_cache_pos;                   /* pos of cache in file     */
  35.  
  36. #define help_pos(ptr) (help_cache_pos+((ptr)-help_cache))
  37.  
  38. static MenuHandle help_menus[HELP_MENUS_MAX]; /* help window menus            */
  39. static Handle help_menu_bar;                  /* help window's menu bar       */
  40. static int help_nb_menus;                     /* nb of menus in help window   */
  41. static int help_nb_items;                     /* total nb of items in menus   */
  42. static int help_menus_items[HELP_MENUS_MAX];  /* offset into help_items_val   */
  43. static long help_items_val[HELP_ITEMS_MAX];   /* index into document body     */
  44. static Rect help_menus_rects[HELP_MENUS_MAX]; /* selection area for each menu */
  45.  
  46. static WindowPtr help_wind = NULL; /* the help window         */
  47. static ControlHandle help_ctl;     /* its vertical scroll bar */
  48.  
  49. static long help_current_page; /* position of current page in doc body */
  50.  
  51. static int help_current_menu;  /* temporary */
  52.  
  53. /*----------------------------------------------------------------------*/
  54.  
  55. static void help_error_set()
  56. {
  57.   ioParam pb;
  58.  
  59.   pb.ioRefNum = help_refnum;
  60.   PBClose( &pb, 0 );
  61.  
  62.   help_error = 1;
  63. }
  64.  
  65. static void help_open_file( filename )
  66. Str255 filename;
  67. {
  68.   ioParam pb;
  69.  
  70.   help_length = 0;
  71.  
  72.   pb.ioNamePtr = filename;
  73.   pb.ioVRefNum = 0;
  74.   pb.ioVersNum = 0;
  75.   pb.ioPermssn = fsRdPerm;
  76.   pb.ioMisc = 0;
  77.   PBOpen( &pb, 0 );
  78.  
  79.   if (pb.ioResult != noErr) { help_error = 1; return; }
  80.  
  81.   help_refnum = pb.ioRefNum;
  82.  
  83.   PBGetEOF( &pb, 0 );
  84.  
  85.   if (pb.ioResult != noErr) { help_error_set(); return; }
  86.  
  87.   help_length = (long)pb.ioMisc;
  88. }
  89.  
  90. static void help_read_block( pos, count, buf, len )
  91. long pos, count;
  92. char *buf;
  93. long *len;
  94. {
  95.   ioParam pb;
  96.  
  97.   *len = 0;
  98.  
  99.   pb.ioRefNum    = help_refnum;
  100.   pb.ioPosMode   = 1; /* relative to start */
  101.   pb.ioPosOffset = pos;
  102.   PBSetFPos( &pb, 0 );
  103.  
  104.   if (pb.ioResult != noErr)
  105.   {
  106.     if (pb.ioResult != eofErr) help_error_set();
  107.     return;
  108.   }
  109.  
  110.   pb.ioRefNum    = help_refnum;
  111.   pb.ioBuffer    = buf;
  112.   pb.ioReqCount  = count;
  113.   pb.ioPosMode   = 1; /* relative to start */
  114.   PBRead( &pb, 0 );
  115.  
  116.   if ((pb.ioResult != noErr) && (pb.ioResult != eofErr))
  117.   { help_error_set(); return; }
  118.  
  119.   *len = pb.ioActCount;
  120. }
  121.  
  122. static void help_load_cache( pos )
  123. long pos;
  124. {
  125.   long len;
  126.   if (pos < 0) pos = 0;
  127.   help_cache_pos = pos;
  128.   len = help_length-pos;
  129.   if (len < 0) len = 0;
  130.   else if (len > HELP_CACHE_LENGTH) len = HELP_CACHE_LENGTH;
  131.   if (len > 0) help_read_block( pos, len, help_cache, &len );
  132.   while (len < HELP_CACHE_LENGTH) help_cache[len++] = HELP_NEWLINE;
  133.   help_cache_end = help_cache+len;
  134.   help_cache[-1] = HELP_NEWLINE;
  135.   help_cache_end[0] = HELP_NEWLINE;
  136. }
  137.  
  138. static void help_load_line( pos )
  139. long pos;
  140. {
  141.   register char *p, *q;
  142.   p = help_cache+(pos-help_cache_pos);
  143.   if ((p > help_cache) && (p < help_cache_end))
  144.   {
  145.     q = p;
  146.     while (*--p != HELP_NEWLINE) ;
  147.     while (*q++ != HELP_NEWLINE) ;
  148.     help_line = p+1;
  149.     help_line_end = q-1;
  150.     if ((help_line > help_cache) && (help_line_end < help_cache_end)) return;
  151.   }
  152.  
  153.   help_load_cache( pos-HELP_CACHE_BEFORE );
  154.   p = help_cache+(pos-help_cache_pos);
  155.   if (p < help_cache) p = help_cache;
  156.   else if (p > help_cache_end) p = help_cache_end;
  157.   q = p;
  158.   while (*--p != HELP_NEWLINE) ;
  159.   while (*q++ != HELP_NEWLINE) ;
  160.   help_line = p+1;
  161.   help_line_end = q-1;
  162. }
  163.  
  164. /*----------------------------------------------------------------------*/
  165.  
  166. static void help_menus_rects_init()
  167. {
  168.   Rect r = { 0, 0, HELP_MENU_H, 0 };
  169.   short *p = *(short **)help_menu_bar;
  170.   register short i = 0;
  171.   short n = *p++; /* #menus * 6 */
  172.   short x = *p++; /* r.right of last menu title */
  173.     
  174.   p += 3; /* skip unused x & handle */
  175.   r.left = *p-5;
  176.   n -= 6;
  177.   do
  178.   {
  179.     p += 3; /* skip unused x & handle */
  180.     r.right = *p-5;
  181.     help_menus_rects[i++] = r;
  182.     r.left = r.right;
  183.     n -= 6;
  184.   } while(n > 0);
  185.   r.right = x-5;
  186.   help_menus_rects[i] = r;
  187. }
  188.  
  189. static void help_menus_init()
  190. {
  191.   unsigned char buffer[100];
  192.   int nb_items;
  193.   int style;
  194.   long value;
  195.   register char *p;
  196.   register int i;
  197.  
  198.   help_nb_menus = 0;
  199.   help_nb_items = 0;
  200.  
  201.   help_cache = help_buffer+1;
  202.  
  203.   help_load_cache( 0 );
  204.   help_load_line( 0 );
  205.   p = help_line;
  206.  
  207.   if (help_error) goto err;
  208.  
  209.   while (*p != HELP_NEWLINE)
  210.   {
  211.     i = 0;
  212.     while (p < help_line_end) { buffer[i+1] = *p++; i++; }
  213.     buffer[0] = i;
  214.     help_menus[help_nb_menus] = NewMenu( HELP_MENUS_ID+help_nb_menus, buffer );
  215.     help_menus_items[help_nb_menus] = help_nb_items;
  216.  
  217.     help_load_line( help_pos(help_line_end+1) );
  218.     p = help_line;
  219.     if (help_error) goto err;
  220.  
  221.     nb_items = 0;
  222.     while (*p != HELP_NEWLINE)
  223.     {
  224.       i = 0;
  225.       while ((unsigned char)*p >= 32) { buffer[i+1] = *p++; i++; }
  226.       buffer[0] = i;
  227.       p++;
  228.       style = 0;
  229.       if (*p == 'i') { style += 2; p++; }
  230.       if (*p == 'b') { style += 1; p++; }
  231.       value = 0;
  232.       while (*p != HELP_NEWLINE) value = value*10 + ((*p++)-'0');
  233.       help_items_val[help_nb_items++] = value;
  234.       nb_items++;
  235.       AppendMenu( help_menus[help_nb_menus], "\p " );
  236.       SetItem( help_menus[help_nb_menus], nb_items, buffer );
  237.       SetItemStyle( help_menus[help_nb_menus], nb_items, style );
  238.  
  239.       help_load_line( help_pos(help_line_end+1) );
  240.       p = help_line;
  241.       if (help_error) goto err;
  242.     }
  243.  
  244.     help_nb_menus++;
  245.  
  246.     help_load_line( help_pos(help_line_end+1) );
  247.     p = help_line;
  248.     if (help_error) goto err;
  249.   }
  250.  
  251.   help_menus_items[help_nb_menus] = help_nb_items;
  252.  
  253.   if (help_nb_menus == 0) help_error_set();
  254.  
  255.   err:
  256.  
  257.   help_prefix = help_pos(help_line_end+1);
  258.  
  259.   ClearMenuBar();
  260.   for (i=0; i<help_nb_menus; i++) InsertMenu( help_menus[i], 0 );
  261.   help_menu_bar = GetMenuBar();
  262.  
  263.   help_menus_rects_init();
  264. }
  265.  
  266. static void help_draw_menu_bar()
  267. {
  268.   int i;
  269.   TextFont( 0 );
  270.   TextFace( 0 );
  271.   TextSize( 12 );
  272.   for (i=0; i<help_nb_menus; i++)
  273.   {
  274.     MoveTo( help_menus_rects[i].left + 9, help_menus_rects[i].bottom - 5 );
  275.     HLock( help_menus[i] );
  276.     DrawString( (*help_menus[i])->menuData );
  277.     HUnlock( help_menus[i] );
  278.   }
  279.   MoveTo( 0, HELP_MENU_H-1 );
  280.   LineTo( HELP_WIND_W, HELP_MENU_H-1 );
  281. }
  282.  
  283. static pascal void help_menu_hook()
  284. {
  285.   Point p;
  286.   WindowPtr wind = FrontWindow();
  287.   long sysA5 = SetA5( GetWRefCon( wind ) );
  288.   GrafPtr save_port;
  289.   GetPort( &save_port );
  290.   SetPort( wind );
  291.   GetMouse( &p );
  292.   if ((p.v < HELP_MENU_H) &&
  293.       !PtInRect( p, &help_menus_rects[help_current_menu] ))
  294.     PostEvent( mouseUp, 0L );
  295.   SetPort( save_port );
  296.   SetA5( sysA5 );
  297. }
  298.  
  299. static long help_menu_select( event )
  300. EventRecord *event;
  301. {
  302.   int i;
  303.   ProcPtr save_menu_hook;
  304.   Point p;
  305.   long selection = 0;
  306.   SetWRefCon( help_wind, SetCurrentA5() );    /* save A5 in window's refCon */
  307.   save_menu_hook = MenuHook;
  308.   MenuHook = (ProcPtr)help_menu_hook;
  309.   while( Button() )    /* don't use StillDown() here !? */
  310.   {
  311.     GetMouse( &p );
  312.     for (i=0; i<help_nb_menus; i++)
  313.     {
  314.       help_current_menu = i;
  315.       if (PtInRect( p, &help_menus_rects[i] ))
  316.       {
  317.         Rect r = help_menus_rects[i];
  318.         InsetRect( &r, 0, 1 );
  319.         r.right += 5;
  320.         InvertRect( &r );
  321.         p.h = r.left + 1;
  322.         p.v = r.bottom + 1;
  323.         LocalToGlobal( &p );
  324.         InsertMenu( help_menus[i], -1 );
  325.         CalcMenuSize( help_menus[i] ); /* Work around Menu Mgr bug */
  326.         selection = PopUpMenuSelect( help_menus[i], p.v, p.h, 0 );
  327.         DeleteMenu( HELP_MENUS_ID + i );
  328.         InvertRect( &r );
  329.         break;
  330.       }
  331.     }
  332.   }
  333.   MenuHook = save_menu_hook;
  334.   return selection;
  335. }
  336.  
  337. static void help_current_page_set( pos )
  338. long pos;
  339. {
  340.   if (pos < 0) pos = 0;
  341.   else if (pos > (help_length-help_prefix)) pos = (help_length-help_prefix);
  342.   help_current_page = pos;
  343. }
  344.  
  345. void help_begin( title, filename )
  346. Str255 title, filename;
  347. {
  348.   Rect r;
  349.  
  350.   help_error = 0;
  351.  
  352.   r.top    = 40;
  353.   r.left   = 28;
  354.   r.bottom = r.top + (HELP_MENU_H+HELP_TOP_SPACE+HELP_LINES*HELP_LINE_H+HELP_BOT_SPACE);
  355.   r.right  = r.left + HELP_WIND_W;
  356.   
  357.   help_wind = NewWindow( 0L, &r, title, 0, 4, (WindowPtr)-1L, 1, 0L );
  358.   if (help_wind == NULL) { help_error = 1; return; }
  359.   SetPort( help_wind );
  360.   TextFont( 0 );
  361.   TextFace( 0 );
  362.   TextSize( 12 );
  363.  
  364.   r.top    = HELP_MENU_H-1;
  365.   r.left   = HELP_WIND_W-15;
  366.   r.bottom = (HELP_MENU_H+HELP_TOP_SPACE+HELP_LINES*HELP_LINE_H+HELP_BOT_SPACE)+1;
  367.   r.right  = HELP_WIND_W+1;
  368.  
  369.   help_ctl = NewControl( help_wind, &r, "\p", 1, 0, 0, (int)HELP_SCROLL_MAX, scrollBarProc, 0 );
  370.   if (help_ctl == NULL) { help_wind = NULL; help_error = 1; return; }
  371.  
  372.   help_open_file( filename );
  373.  
  374.   if (!help_error) help_menus_init();
  375.  
  376.   if (help_error) help_wind = NULL;
  377.  
  378.   help_current_page_set( 0 );
  379. }
  380.  
  381. void help_end()
  382. {
  383.   if (help_wind != NULL)
  384.   {
  385.     DisposeWindow( help_wind );
  386.     help_error_set();
  387.   }
  388. }
  389.  
  390. /*----------------------------------------------------------------------*/
  391.  
  392. /* Display of the document's text */
  393.  
  394. static int help_offsv( f )
  395. int f;
  396. {
  397.   switch (f%3)
  398.   {
  399.     case 0: switch (f/9)
  400.             { case 0: return 0; case 1: return 1; case 2: return 0; }
  401.     case 1: return 2;
  402.     case 2: return -2;
  403.   }
  404. }
  405.  
  406. static int help_offsh(f)
  407. int f;
  408. { if (f/3%3 == 2) return -1; else return 0; }
  409.  
  410. static void help_select_font( f, oldf )
  411. int f, oldf;
  412. {
  413.   switch (f/9)
  414.   {
  415.     case 0: TextFont(1); TextSize(9);  break; /* Geneva, 9 pt   */
  416.     case 1: TextFont(1); TextSize(12); break; /* Geneva, 12 pt  */
  417.     case 2: TextFont(4); TextSize(9);  break; /* Monaco, 9 pt   */
  418.   }
  419.   switch (f/3%3)
  420.   {
  421.     case 0: TextFace(0); break;               /* plain          */
  422.     case 1: switch (f/9)
  423.             {
  424.               case 0: TextFace(1);  break;    /* bold           */
  425.               case 1: TextFace(5);  break;    /* bold underline */
  426.               case 2: TextFace(33); break;    /* bold condensed */
  427.             }
  428.             break;
  429.     case 2: TextFace(2); break;               /* italic         */
  430.   }
  431.   Move( help_offsh(f)-help_offsh(oldf), help_offsv(f)-help_offsv(oldf) );
  432. }
  433.  
  434. /* drawing of currently cached line */
  435.  
  436. static void help_draw_line()
  437. {
  438.   register char *p;
  439.   int f;
  440.  
  441.   help_select_font( 0, 0 );
  442.   f = 0;
  443.  
  444.   p = help_line;
  445.   while (p < help_line_end)
  446.   {
  447.     register unsigned char c = *p;
  448.     char *last = p;
  449.     while ((c >= 32) && (c <= 227)) { p++; c = *p; }
  450.     if (last < p) DrawText( last, 0, p-last );
  451.     p++;
  452.     if (c == 13)
  453.       goto line_end;
  454.     else if (c < 32)
  455.       Move( c, 0 );
  456.     else if (c > 227)
  457.     {
  458.       help_select_font( 255-c, f );
  459.       f = 255-c;
  460.     }
  461.   }
  462.   line_end: ;
  463. }
  464.  
  465. /* drawing of current page from lines 'lo' to 'hi-1' */
  466.  
  467. static void help_draw_lines( lo, hi )
  468. int lo, hi;
  469. {
  470.   long pos = help_current_page+help_prefix;
  471.   int i;
  472.  
  473.   for (i=0; i<hi; i++)
  474.   {
  475.     help_load_line( pos );
  476.     if (help_error) return;
  477.     if (i >= lo)
  478.     {
  479.       MoveTo( HELP_LEFT_SPACE, HELP_MENU_H+HELP_TOP_SPACE+i*HELP_LINE_H+HELP_LINE_H-HELP_DESCENT );
  480.       help_draw_line();
  481.     }
  482.     pos = help_pos(help_line_end+1);
  483.   }
  484. }
  485.  
  486. static void help_thumb_to_current_page()
  487. {
  488.   int val = help_current_page*((long)HELP_SCROLL_MAX)/(help_length-help_prefix)+1;
  489.   if (GetCtlValue(help_ctl) != val) SetCtlValue( help_ctl, val );
  490. }
  491.  
  492. static void help_draw_current_page()
  493. {
  494.   Rect r;
  495.   GrafPtr save_port;
  496.  
  497.   GetPort( &save_port );
  498.   SetPort( help_wind );
  499.  
  500.   help_thumb_to_current_page();
  501.  
  502.   r.top = HELP_MENU_H; r.left = 0; r.bottom = 32000; r.right = HELP_WIND_W-15;
  503.   EraseRect( &r );
  504.  
  505.   help_draw_lines( 0, HELP_LINES );
  506.  
  507.   SetPort( save_port );
  508. }
  509.  
  510. /*----------------------------------------------------------------------*/
  511.  
  512. void help_show()
  513. {
  514.   if (help_wind == NULL)
  515.     SysBeep( 10 );
  516.   else
  517.   {
  518.     SelectWindow( help_wind );
  519.     ShowWindow( help_wind );
  520.   }
  521. }
  522.  
  523. void help_hide()
  524. {
  525.   if (help_wind == NULL)
  526.     SysBeep( 10 );
  527.   else
  528.     HideWindow( help_wind );
  529. }
  530.  
  531. void help_hide_if_frontmost()
  532. {
  533.   if ((help_wind != NULL) && (FrontWindow() == help_wind))
  534.     HideWindow( help_wind );
  535. }
  536.  
  537. void help_find( name )
  538. Str255 name;
  539. {
  540.   int id, item, len;
  541.   Str255 str;
  542.   if (help_wind == NULL) return;
  543.   if (name[0] > 0)
  544.   {
  545.     if ((name[0] == 1) && (name[1] == '-')) name[1] = 208; /* hack for - */
  546.     id = HELP_INDEX_START;
  547.     while (id < help_nb_menus)
  548.     {
  549.       item = help_menus_items[id+1]-help_menus_items[id];
  550.       while (item > 0)
  551.       {
  552.         GetItem( help_menus[id], item, &str );
  553.         len = str[0];
  554.         if (len == name[0])
  555.         {
  556.           while (len>0) if (str[len] == name[len]) len--; else break;
  557.           if (len == 0) goto found;
  558.         }
  559.         item--;
  560.       }
  561.       id++;
  562.     }
  563.     SysBeep(10);
  564.   }
  565.   id = 0;
  566.   item = 1;
  567.  
  568.   found:
  569.   help_current_page_set( help_items_val[help_menus_items[id]+item-1] );
  570.   help_draw_current_page();
  571.   if (!((WindowPeek)help_wind)->visible)
  572.   {
  573.     SelectWindow( help_wind );
  574.     ShowWindow( help_wind );
  575.   }
  576. }
  577.  
  578. static void help_activate( activate )
  579. int activate;
  580. {
  581.   if (help_wind != NULL)
  582.     if (activate)
  583.       ShowControl( help_ctl );
  584.     else
  585.       HideControl( help_ctl );
  586. }
  587.  
  588. static void help_scroll_lines( n ) /* n = lines to scroll forward */
  589. int n;
  590. {
  591.   if (n != 0)
  592.   {
  593.     long last_pos;
  594.     int i = n;
  595.     int j = 0;
  596.     help_load_line( help_current_page+help_prefix );
  597.     if (help_error) return;
  598.     help_current_page_set( help_pos(help_line)-help_prefix );
  599.     while (i != 0)
  600.     {
  601.       last_pos = help_current_page;
  602.       if (i>0)
  603.       {
  604.         help_load_line( help_pos(help_line_end+1) );
  605.         i--;
  606.       }
  607.       else
  608.       {
  609.         help_load_line( help_pos(help_line-1) );
  610.         i++;
  611.       }
  612.       if (help_error) return;
  613.       help_current_page_set( help_pos(help_line)-help_prefix );
  614.       if (help_current_page == last_pos) break;
  615.       j++;
  616.     }
  617.     if (j != 0)
  618.     {
  619.       Rect r;
  620.       RgnHandle rgn;
  621.       r.left = 0;
  622.       r.right = HELP_WIND_W-15;
  623.       r.top = HELP_MENU_H+HELP_TOP_SPACE;
  624.       r.bottom = HELP_MENU_H+HELP_TOP_SPACE+HELP_LINE_H*HELP_LINES;
  625.       rgn = NewRgn();
  626.       if (n > 0)
  627.       {
  628.         ScrollRect( &r, 0, -HELP_LINE_H*j, rgn );
  629.         help_draw_lines( HELP_LINES-j, HELP_LINES );
  630.       }
  631.       else
  632.       {
  633.         ScrollRect( &r, 0, HELP_LINE_H*j, rgn );
  634.         help_draw_lines( 0, j );
  635.       }
  636.       DisposeRgn( rgn );
  637.       if (help_error) return;
  638.       help_thumb_to_current_page();
  639.     }
  640.   }
  641. }
  642.  
  643. static pascal void help_scroll_proc( ctl, part )
  644. ControlHandle ctl;
  645. short part;
  646. {
  647.   int n = 0;
  648.   switch (part)
  649.   {
  650.     case inUpButton  : n = -1; break;
  651.     case inDownButton: n =  1; break;
  652.     case inPageUp    : n = -(HELP_LINES-2); break;
  653.     case inPageDown  : n =  (HELP_LINES-2); break;
  654.   }
  655.   help_scroll_lines( n );
  656. }
  657.  
  658. static void help_scroll( event, part )
  659. EventRecord *event;
  660. int part;
  661. {
  662.   long oldval, newval;
  663.   switch (part)
  664.   {
  665.     case inUpButton:
  666.     case inDownButton:
  667.     case inPageUp:
  668.     case inPageDown:
  669.       TrackControl( help_ctl, event->where, (ProcPtr)help_scroll_proc );
  670.       break;
  671.     case inThumb:
  672.       oldval = GetCtlValue( help_ctl );
  673.       TrackControl( help_ctl, event->where, 0L );
  674.       newval = GetCtlValue( help_ctl );
  675.       if ((newval != oldval) || (newval == 0) || (newval == HELP_SCROLL_MAX))
  676.       {
  677.         help_current_page_set( newval*(help_length-help_prefix)/((long)HELP_SCROLL_MAX) );
  678.         help_draw_current_page();
  679.       }
  680.       break;
  681.     default:
  682.       SysBeep( 10 );
  683.       break;
  684.   }
  685. }
  686.  
  687. static void help_menu_selection( event )
  688. EventRecord *event;
  689. {
  690.   long selection = help_menu_select( event );
  691.   if (selection != 0)
  692.   {
  693.     int id = selection>>16;
  694.     int item = selection & 0xffff;
  695.     if ((id >= HELP_MENUS_ID) && (id < HELP_MENUS_ID+help_nb_menus))
  696.     {
  697.       help_current_page_set( help_items_val[help_menus_items[id-HELP_MENUS_ID]+item-1] );
  698.       help_draw_current_page();
  699.     }
  700.   }
  701. }
  702.  
  703. static void help_update()
  704. {
  705.   GrafPtr save_port;
  706.   GetPort( &save_port );
  707.   SetPort( help_wind );
  708.   BeginUpdate( help_wind );
  709.   DrawControls( help_wind );
  710.   help_draw_menu_bar();
  711.   help_draw_current_page();
  712.   EndUpdate( help_wind );
  713. }
  714.  
  715. int help_event( event )
  716. EventRecord *event;
  717. {
  718.   WindowPtr w;
  719.   ControlHandle ctl;
  720.   GrafPtr save_port;
  721.   int part;
  722.  
  723.   if (help_wind != NULL)
  724.     switch (event->what)
  725.     {
  726.       case mouseDown:
  727.         part = FindWindow( event->where, &w );
  728.         if (w == help_wind)
  729.         {
  730.           switch (part)
  731.           { case inGoAway:
  732.               if (TrackGoAway( w, event->where )) help_hide();
  733.               break;
  734.             case inDrag:
  735.               DragWindow( w, event->where, &screenBits.bounds );
  736.               break;
  737.             case inContent:
  738.               if (w != FrontWindow())
  739.                 SelectWindow(w);
  740.               else
  741.               {
  742.                 GetPort( &save_port );
  743.                 SetPort( w );
  744.                 GlobalToLocal( &event->where );
  745.                 if (event->where.v < HELP_MENU_H)
  746.                   help_menu_selection( event );
  747.                 else
  748.                 {
  749.                   part = FindControl( event->where, w, &ctl );
  750.                   if (ctl == help_ctl) help_scroll( event, part );
  751.                 }
  752.                 SetPort( save_port );
  753.               }
  754.               break;
  755.           }
  756.           return 1;
  757.         }
  758.         break;
  759.       case activateEvt:
  760.         if ((WindowPtr)event->message == help_wind)
  761.         { help_activate( event->modifiers & activeFlag ); return 1; }
  762.         break;
  763.       case updateEvt: 
  764.         if ((WindowPtr)event->message == help_wind)
  765.         { help_update(); return 1; }
  766.         break;
  767.     }
  768.  
  769.   return 0;
  770. }
  771.  
  772. /*----------------------------------------------------------------------*/
  773.